// Incredibly simple database wrapper
// Copyright 2006 (C) Ralph Thomas

#ifndef MISSION_UTIL_DB_H
#define MISSION_UTIL_DB_H

#include <boost/filesystem/path.hpp>
#include <boost/function.hpp>
#include <adobe/dictionary.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/signal.hpp>

namespace util {
	struct dbImpl;
	//
	/// The db class wraps a simple SQL database. It can open and lock
	/// the given database file. This class is used by the database
	/// model for all of it's database access.
	///
	/// This interface was designed to wrap the SQLite database engine.
	//
	class db {
		dbImpl* _impl;
		friend class dbImpl;
		db( const boost::filesystem::path& path, bool create = false );
	  public:
		~db();
		//
		/// This function gets invoked for each row with a dictionary
		/// containing the column name -> column value map.
		//
		typedef boost::function<void (const adobe::dictionary_t&)> on_row_proc_t;
		//
		/// The db wrapper will call this function any time the
		/// underlying database changes as a result of a query.
		///
		/// The first argument is the name of the database that
		/// changed. The second argument is the name of the table
		/// that changed.
		//
		typedef boost::function<void ()> change_proc_t;
		//
		/// Return the db wrapper for the given path.
		///
		/// \param	path	the path to the database file
		/// \return	a db wrapper or an exception if the file
		///		couldn't be opened or created.
		//
		static boost::shared_ptr<db> fromPath( const boost::filesystem::path& p );
		//
		/// Execute some SQL on the database that doesn't return
		/// any results (such as an INSERT command).
		///
		/// \param	query	the SQL to execute.
		/// \return	the last inserted row id.
		//
		long long int execute( const std::string& query );
		//
		/// Query the database for some results. The given function
		/// is called once for each row returned.
		///
		/// \param	query	the SQL query.
		/// \param	on_row	the function to call with a dictionary for the row.
		//
		void query( const std::string& query, on_row_proc_t on_row );
		//
		/// Query the database for some results, returning them
		/// in an adobe::dictionary_t of cow_vector<type>s. The
		/// type is predicated by the type of the column.
		///
		/// \param	query	the SQL query.
		/// \param	results	dictionary to insert the results into.
		/// \return	the number of rows in the results.
		//
		unsigned int query( const std::string& query, adobe::dictionary_t& results );
		//
		/// Set the function to call when the database has changed.
		///
		/// \param	proc	the function to call when changed.
		//
		boost::signals::connection on_change( const change_proc_t& proc );
		//
		/// Escape the string use with the database.
		///
		/// \param	s	the string to escape.
		/// \return	the escaped string.
		//
		static std::string escape( const std::string& s );
	};
	typedef boost::shared_ptr<db> db_ptr_t;
};

#endif

